﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using CSharpHelpers.IOs;
using Microsoft.VisualBasic;

namespace CSharpHelpers.Encodes
{
    /// <summary>
    /// 语言帮助类
    /// </summary>
    public static class LanguageHelper
    {
        // 编码格式
        private static string CODE_ISO_8859 = "iso-8859-1";
        private static string CODE_BIG5 = "big5";
        private static string CODE_UTF8 = "utf-8";
        private static string CODE_GBK = "gbk";
        private static string CODE_GB_2313 = "gb2312";
        private static string CODE_GB_18030 = "gb18030";

        // 拉丁字符
        private static Dictionary<int, string> latinStrsDic;
        private static readonly int[] latinValues = { 128, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 159, 142, 158 };
        private static readonly string[] latinStrings = { "€", "‚", "ƒ", "„", "…", "†", "‡", "ˆ", "‰", "Š", "‹", "Œ", "‘", "’", "“", "”", "•", "–", "—", "˜", "™", "š", "›", "œ", "Ÿ", "Ž", "ž" };

        #region 普通转码

        /// <summary>
        /// 转码
        /// </summary>
        /// <param name="origiEncode"></param>
        /// <param name="newEncode"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetNewEncodeStr(string origiEncode, string newEncode, string str)
        {
            // str本身的编码
            var selfEncode = Encoding.GetEncoding(origiEncode);
            var selfArr = selfEncode.GetBytes(str);

            // 目标编码
            var targetEncode = Encoding.GetEncoding(newEncode);
            var targetStr = targetEncode.GetString(selfArr);

            return targetStr;
        }

        /// <summary>
        /// ISO->BIG5
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ConvertIso2Big5(string str)
        {
            var targetStr = GetNewEncodeStr(CODE_ISO_8859, CODE_BIG5, str);
            return targetStr;
        }

        /// <summary>
        /// BIG5->ISO
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ConvertBig52Iso(string str)
        {
            var targetStr = GetNewEncodeStr(CODE_BIG5, CODE_ISO_8859, str);
            return targetStr;
        }

        /// <summary>
        /// ISO->UTF-8
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ConvertIso2Utf8(string str)
        {
            var targetStr = GetNewEncodeStr(CODE_ISO_8859, CODE_UTF8, str);
            return targetStr;
        }

        /// <summary>
        /// UTF-8->ISO
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ConvertUtf82Iso(string str)
        {
            var targetStr = GetNewEncodeStr(CODE_UTF8, CODE_ISO_8859, str);
            return targetStr;
        }

        #endregion

        #region 转码为拉丁文字符

        /// <summary>
        /// 获取拉丁字符串
        /// </summary>
        /// <returns></returns>
        public static string GetLatinStr(string str)
        {
            // 简体语言系统
            //var data = Encoding.GetEncoding(CODE_GBK).GetBytes(str);

            // 繁体语言系统
            str = ConvertSimple2Traditinal(str);
            var data = Encoding.GetEncoding(CODE_BIG5).GetBytes(str);

            var result = "";
            foreach (var t in data)
            {
                if (t == 128 || (t >= 130 && t <= 140) || (t >= 145 && t <= 156) || (t >= 158 && t <= 159) || t == 142)
                {
                    result += GetLatinChar(t);
                }
                else
                {
                    result += (char)t;
                }
            }

            result = result.Replace("\\", "\\\\");

            return result;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public static void InitLatinCharDic()
        {
            latinStrsDic = new Dictionary<int, string>();
            for (var i = 0; i < latinStrings.Length; i++)
            {
                var key = latinValues[i];
                var value = latinStrings[i];
                if (!latinStrsDic.ContainsKey(key))
                {
                    latinStrsDic.Add(key, value);
                }
            }
        }

        /// <summary>
        /// 获取拉丁字符
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetLatinChar(int key)
        {
            var str = string.Empty;
            if (latinStrsDic.ContainsKey(key))
            {
                str = latinStrsDic[key];
            }

            return str;
        }

        #endregion

        #region 常用方法

        /// <summary>
        /// 判断字符串是否为中文
        /// </summary>
        /// <returns></returns>
        public static bool IsChinese(string str)
        {
            var rg = new Regex("^[\u4e00-\u9fa5]$");
            return str.Any(t => rg.IsMatch(t.ToString()));
        }

        /// <summary>
        /// 判断字符串是否为简体中文
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsSimpleChinese(string str)
        {
            var isSimpleChinese = str.Select(IsSimpleChinese).All(isSimple => isSimple);
            return isSimpleChinese;
        }

        /// <summary>
        /// 判断字符是否为简体中文
        /// 原理：
        /// gb2312-1980的前128个跟ASCII是一致的,而且unicode的前128个跟ASCII也是一致的。
        /// 基于gb2312-1980只包含简体中文的特性，可以用来判断简体与繁体
        /// </summary>
        /// <returns></returns>
        public static bool IsSimpleChinese(char chr)
        {
            var str = chr.ToString();
            var gb2312Bytes = Encoding.GetEncoding(CODE_GB_2313).GetBytes(str);
            if (gb2312Bytes.Length != 2)
            {
                return false;
            }

            var isTraditional = gb2312Bytes[0] >= 0xB0 && gb2312Bytes[0] <= 0xF7 
                                && gb2312Bytes[1] >= 0xA1 && gb2312Bytes[1] <= 0xFE;

            return isTraditional;
        }

        /// <summary>
        /// 简体转繁体
        /// </summary>
        /// <param name="strSimple"></param>
        /// <returns></returns>
        public static string ConvertSimple2Traditinal(string strSimple)
        {
            var strTraditional = Strings.StrConv(strSimple, VbStrConv.TraditionalChinese);
            return strTraditional;
        }

        /// <summary>
        /// 繁体转简体
        /// </summary>
        /// <param name="strTraditional"></param>
        /// <returns></returns>
        public static string ConvertTraditinal2Simple(string strTraditional)
        {
            var strSimple = Strings.StrConv(strTraditional, VbStrConv.SimplifiedChinese);
            return strSimple;
        }

        #endregion

        /// <summary>
        /// 字符串轉ASCII碼
        /// </summary>
        /// <param name="character"></param>
        /// <returns></returns>
        public static int GetAsciiFromStr(string character)
        {
            int intAsciiCode = -1;
            if (character.Length == 1)
            {
                try
                {
                    System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
                    intAsciiCode = asciiEncoding.GetBytes(character)[0];
                }
                catch (Exception e)
                {
                    SystemLog.Error("轉換字符異常：" + e);
                }
            }

            return intAsciiCode;
        }

        public static string GetAsciiFromNumber(int number)
        {
            var array = new byte[] { (byte)number };
            var str = Encoding.ASCII.GetString(array);

            return str;
        }

        /// <summary>
        /// ASCII碼轉字符串
        /// </summary>
        /// <param name="asciiCode"></param>
        /// <returns></returns>
        public static string GetStrFromAscii(int asciiCode)
        {
            string strCharacter = string.Empty;
            if (asciiCode >= 0 && asciiCode <= 255)
            {
                try
                {
                    System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
                    byte[] byteArray = new byte[] { (byte)asciiCode };
                    strCharacter = asciiEncoding.GetString(byteArray);
                }
                catch (Exception e)
                {
                    SystemLog.Error("轉換字符異常：" + e);
                }
            }

            return strCharacter;
        }
    }
}
